package com.bingxue.edu.management.system.service;

import cn.hutool.core.util.ObjectUtil;
import com.bingxue.edu.common.enums.CommonStatusEnum;
import com.bingxue.edu.framework.exception.BusinessException;
import com.bingxue.edu.framework.exception.SystemException;
import com.bingxue.edu.framework.job.QuartzSchedulerService;
import com.bingxue.edu.framework.mybatis.base.BaseService;
import com.bingxue.edu.management.system.mapper.ScheduleJobMapper;
import com.bingxue.edu.management.system.model.entity.ScheduleJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import static com.bingxue.edu.management.system.model.entity.table.ScheduleJobTableDef.SCHEDULE_JOB;

/**
* 定时任务业务实现类
*
* @author panbo
* @since 2024/08/02 13:34
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ScheduleJobService extends BaseService<ScheduleJobMapper, ScheduleJob> {

    private final QuartzSchedulerService quartzSchedulerService;

    /**
     * 创建任务
     * @param job 任务信息
     */
    public void createJob(ScheduleJob job) {
        boolean success = super.save(job);
        if (!success) {
            throw new SystemException("创建任务失败");
        }
        // 只有启用情况才加入任务队列
        if (CommonStatusEnum.ENABLED.equals(job.getStatus())) {
            quartzSchedulerService.addJob(job);
        }
        log.info("创建任务成功, {}", job);
    }

    /**
     * 更新任务
     * @param req 更新任务请求
     */
    public void updateJob(ScheduleJob req) {
        // 更新后对系统的定时任务进行操作
        ScheduleJob oldJob = getById(req.getId());
        boolean success = super.updateById(req);
        if (!success) {
            throw new SystemException("更新任务失败");
        }
        // job如果存在且参数发生了变化，那么先触发删除原来的job
        if (quartzSchedulerService.existJob(req.getId()) &&
                (ObjectUtil.notEqual(oldJob.getStatus(), req.getStatus())
                        || ObjectUtil.notEqual(oldJob.getJobKey(), req.getJobKey())
                        || ObjectUtil.notEqual(oldJob.getCron(), req.getCron())
                        || ObjectUtil.notEqual(oldJob.getParamJson(), req.getParamJson())
                        || ObjectUtil.notEqual(oldJob.getInitStrategy(), req.getInitStrategy()))
        ) {
            quartzSchedulerService.deleteJob(req.getId());
            // 只有启用情况才加入任务队列
            if (CommonStatusEnum.ENABLED.equals(req.getStatus())) {
                quartzSchedulerService.addJob(req);
            }
        }
    }

    /**
     * 删除任务
     * @param jobId 任务id
     */
    public void deleteJob(Serializable jobId) {
        quartzSchedulerService.deleteJob((String) jobId);
        super.removeById(jobId);
    }

    /**
     * 执行一次任务
     * @param jobId 任务id
     */
    public void executeOnceJob(String jobId) {
        // 如果已经存在job，那么直接恢复，否则添加job
        if (!quartzSchedulerService.existJob(jobId)) {
            ScheduleJob entity = this.getById(jobId);
            if (entity == null) {
                throw new BusinessException("任务不存在");
            }
            quartzSchedulerService.addJobExecuteOnce(entity);
        } else {
            quartzSchedulerService.runJob(jobId);
        }
    }

    /**
     * 对${@link ScheduleJob}进行操作 【启用/停用】
     * <p>
     * 操作数据库的任务记录
     * @param jobId 任务id
     * @param jobStatus 任务状态
     */
    public void changeScheduleJobStatus(String jobId, CommonStatusEnum jobStatus) {
        boolean success = this.updateChain().where(SCHEDULE_JOB.ID.eq(jobId)).set(SCHEDULE_JOB.STATUS, jobStatus).update();
        if (!success) {
            throw new BusinessException("更新任务失败");
        }

        if (CommonStatusEnum.ENABLED.equals(jobStatus)) {
            // 恢复
            // 如果已经存在job，那么直接恢复，否则添加job
            if (quartzSchedulerService.existJob(jobId)) {
                quartzSchedulerService.resumeJob(jobId);
            } else {
                ScheduleJob entity = this.getById(jobId);
                if (entity == null) {
                    throw new BusinessException("任务不存在");
                }
                quartzSchedulerService.addJob(entity);
            }
        } else if (CommonStatusEnum.DISABLED.equals(jobStatus)) {
            // 停止
            quartzSchedulerService.pauseJob(jobId);
        }
    }

    /**
     * 获取所有被{@link com.bingxue.edu.framework.job.DynamicJob}注解的job
     */
    public List<Map<String, Object>> getAllJobs() {
        return quartzSchedulerService.loadAllJobs();
    }
}
